package com.ys.otms.services;

import com.ys.otms.dao.IShipDao;
import com.ys.otms.dao.ITransportPlanDao;
import com.ys.otms.dto.BerthInfoDto;
import com.ys.otms.dto.ShipXyInfoDto;
import com.ys.otms.utils.*;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.NumberFormat;
import java.util.*;

@Service
public class ShipXyServices {

    private static Logger logger = LoggerFactory.getLogger(ShipXyServices.class);

    private static Map<Integer,String> shipState = new HashMap<>();
    //todo 11-14问船讯网要
    static {
        shipState.put(0,"在航（主机推)");
        shipState.put(1,"锚泊");
        shipState.put(2,"失控");
        shipState.put(3,"操纵受限");
        shipState.put(4,"吃水受限");
        shipState.put(5,"靠泊");
        shipState.put(6,"搁浅");
        shipState.put(7,"捕捞作业");
        shipState.put(8,"靠帆船提供动力");
        shipState.put(9,"为将来 HSC 航行状态修正保留");
        shipState.put(10,"为将来 WIG 航行状态修正保留");
    }

    @Autowired
    private IShipDao iShipDao;

    @Scheduled(fixedDelay = 1800 * 1000)
    //30分钟执行一次
    public void getShipXyInfo() {
        Long startTime = new Date().getTime();
        logger.info("ShipXyServices getShipXyInfo start date:{}", DateUtil.getStandardNowTime());
        //1、获取数据库中所有的船舶id和mmsi
        List<ShipXyInfoDto> shipXyInfoDtoList1 = selectAllShipMMSI();
        if (ListUtil.isNotEmpty(shipXyInfoDtoList1)) {
            StringBuilder sb = new StringBuilder();
            for (ShipXyInfoDto shipInfoDto : shipXyInfoDtoList1) {
                if (StringUtil.isNotEmpty(shipInfoDto.getMmsi())) {
                    sb.append(shipInfoDto.getMmsi()).append(",");
                }
            }
            if (sb.length() > 0) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("shipIds", sb.substring(0, sb.length() - 1));
                JSONObject jsonObject2 = ShipXyAPIUtil.getManyShip(jsonObject);
                if (jsonObject2 !=null){
                    JSONArray jsonArray = JsonUtil.getJSONArray(jsonObject2,"data");
                    if (null != jsonArray) {
                        List<ShipXyInfoDto> shipXyInfoDtoList = new ArrayList<>();
                        for (int i = 0; i <jsonArray.size(); i++) {
                            JSONObject jsonObject3 = jsonArray.getJSONObject(i);
                            String mmsi = JsonUtil.getJSONObjectString2(jsonObject3,"mmsi");
                            String shipType = JsonUtil.getJSONObjectString2(jsonObject3,"shiptype");
                            String shipName = JsonUtil.getJSONObjectString2(jsonObject3,"name");
                            String length = JsonUtil.getJSONObjectString2(jsonObject3,"length");
                            String width = JsonUtil.getJSONObjectString2(jsonObject3,"width");
                            String draught = JsonUtil.getJSONObjectString2(jsonObject3,"draught");
                            String destStd = JsonUtil.getJSONObjectString2(jsonObject3,"dest_std");
                            String etaStd = JsonUtil.getJSONObjectString2(jsonObject3,"eta_std");
                            String navistatCode = JsonUtil.getJSONObjectString2(jsonObject3,"navistat");
                            NumberFormat nf = NumberFormat.getInstance();
                            nf.setGroupingUsed(false);
                            String lat = nf.format(jsonObject3.getLong("lat")/1000000.0);
                            String lon = nf.format(jsonObject3.getLong("lon")/1000000.0);

                            String sog = JsonUtil.getJSONObjectString2(jsonObject3,"sog");
                            String cog = null;
                            if (StringUtil.isNotEmpty(JsonUtil.getJSONObjectString2(jsonObject3,"cog"))) {
                                cog = String.valueOf(jsonObject3.getLong("cog")/100.0);
                            }
                            String hdg = null;
                            if (StringUtil.isNotEmpty(JsonUtil.getJSONObjectString2(jsonObject3,"hdg"))) {
                                hdg = String.valueOf(jsonObject3.getLong("hdg")/100.0);
                            }
                            String lastTime = JsonUtil.getJSONObjectString2(jsonObject3,"lasttime");
                            ShipXyInfoDto shipXyInfoDto = new ShipXyInfoDto(mmsi,shipType,shipName,length,width,draught,destStd,etaStd,lat,null,lon,null,hdg,cog,sog);

                            if (StringUtil.isNotEmpty(navistatCode)) {
                                String state = shipState.get(Integer.parseInt(navistatCode));
                                if (StringUtil.isNotEmpty(state)) {
                                    shipXyInfoDto.setNavistat(state);
                                    shipXyInfoDto.setNavistatCode(navistatCode);
                                }
                                else {
                                    shipXyInfoDto.setNavistat("N/A");
                                    shipXyInfoDto.setNavistatCode(null);
                                }
                            }

                            if (StringUtil.isNotEmpty(lastTime)) {
                                shipXyInfoDto.setLastTime(DateUtil.getStandardTime(Long.parseLong(lastTime) * 1000));
                            }
                            shipXyInfoDtoList.add(shipXyInfoDto);
                        }
                        insertShipXyInfoBatch(shipXyInfoDtoList1, shipXyInfoDtoList);
                    }
                }
            }
        }
        Long endTime = new Date().getTime();
        logger.info("getShipXyInfo time:{}", DateUtil.formatDuring(endTime-startTime));
    }


    private void insertShipXyInfoBatch(List<ShipXyInfoDto> shipInfoList, List<ShipXyInfoDto> shipXyInfoDtoList) {
        List<ShipXyInfoDto> allNavistatCodeList = iShipDao.selectAllNavistatCode();
        //修改坐标
        int length = shipXyInfoDtoList.size();
        StringBuffer sb = new StringBuffer();
        List<ShipXyInfoDto> shipXyInfoDtoList1 = new ArrayList<>();
        for(int i = 0; i < length; i++) {
            ShipXyInfoDto shipXyInfoDto = shipXyInfoDtoList.get(i);
            if (i%40 == 0 && i != 0) {
                getLocations(sb, shipXyInfoDtoList, shipXyInfoDtoList1);
                sb =  new StringBuffer();
                shipXyInfoDtoList1 = new ArrayList<>();
            }
            if (StringUtil.isNotEmpty(shipXyInfoDto.getLon()) && StringUtil.isNotEmpty(shipXyInfoDto.getLat())
                    && checkZBIsRight(shipXyInfoDto.getLon())  && checkZBIsRight(shipXyInfoDto.getLat()) ) {
                sb.append(shipXyInfoDto.getLon()).append(",").append(shipXyInfoDto.getLat()).append("|");
                shipXyInfoDtoList1.add(shipXyInfoDto);
            }
        }
        if (sb.length() > 0) {
            getLocations(sb, shipXyInfoDtoList, shipXyInfoDtoList1);
        }

        //逆解析
        StringBuffer stringBuffer = new StringBuffer();
        List<ShipXyInfoDto> shipXyInfoDtoList11 = new ArrayList<>();
        for(int i = 0; i < shipXyInfoDtoList.size(); i++) {
            ShipXyInfoDto shipXyInfoDto = shipXyInfoDtoList.get(i);
            if (i%20 == 0 && i != 0) {
                getCityName4GD(stringBuffer, shipXyInfoDtoList, shipXyInfoDtoList11);
                stringBuffer =  new StringBuffer();
                shipXyInfoDtoList11 = new ArrayList<>();
            }
            if (StringUtil.isNotEmpty(shipXyInfoDto.getGLon()) && StringUtil.isNotEmpty(shipXyInfoDto.getGLat())) {
                stringBuffer.append(shipXyInfoDto.getGLon()).append(",").append(shipXyInfoDto.getGLat()).append("|");
                shipXyInfoDtoList11.add(shipXyInfoDto);
            }
        }
        if (stringBuffer.length() > 0) {
            getCityName4GD(stringBuffer, shipXyInfoDtoList, shipXyInfoDtoList11);
        }

        for (ShipXyInfoDto shipXyInfoDto : shipXyInfoDtoList) {
            for(ShipXyInfoDto shipInfoDto : shipInfoList) {
                if (shipXyInfoDto.getMmsi().equals(shipInfoDto.getMmsi())) {
                    if (StringUtil.isEmpty(shipInfoDto.getCityName())) {
                        shipXyInfoDto.setCityNames(shipXyInfoDto.getCityName());
                    }
                    else {
                        if (("," + shipInfoDto.getCityName() + ",").contains("," + shipXyInfoDto.getCityName() + ",")) {
                            shipXyInfoDto.setCityNames(shipInfoDto.getCityName());
                        }
                        else {
                            shipXyInfoDto.setCityNames(shipInfoDto.getCityName() + "," + shipXyInfoDto.getCityName());
                        }
                    }
                    break;
                }
            }
        }

        //批量插入，1000条一次
        int size = shipXyInfoDtoList.size();
        int x = size/1000;
        int y = size%1000;
        for (int i = 0; i < x; i++) {
            int start = i*1000;
            int end = (i + 1) * 1000;
            List<ShipXyInfoDto> subList = shipXyInfoDtoList.subList(start,end);
            iShipDao.insertShipXyInfoBatch(subList);
            iShipDao.insertShipTrack(subList);
            iShipDao.updateCityName4ShipInfo(subList);
        }

        if (y > 0) {
            List<ShipXyInfoDto> subList = shipXyInfoDtoList.subList(x*1000,size);
            iShipDao.insertShipXyInfoBatch(subList);
            iShipDao.insertShipTrack(subList);
            iShipDao.updateCityName4ShipInfo(subList);
        }
        insertBerthInfoBatch(allNavistatCodeList, shipXyInfoDtoList);
    }

    private void insertBerthInfoBatch(List<ShipXyInfoDto> allNavistatCodeList, List<ShipXyInfoDto> shipXyInfoDtoList) {
        List<BerthInfoDto> berthInfoDtoList = new ArrayList<>();
        for (ShipXyInfoDto shipXyInfoDto : shipXyInfoDtoList) {
            if("5".equals(shipXyInfoDto.getNavistatCode())) {
                for (ShipXyInfoDto shipXyInfoDto1 : allNavistatCodeList) {
                    if (shipXyInfoDto.getMmsi().equals(shipXyInfoDto1.getMmsi()) && !"5".equals(shipXyInfoDto1.getNavistatCode())) {
                        BerthInfoDto berthInfoDto = new BerthInfoDto(shipXyInfoDto.getMmsi(), shipXyInfoDto.getNavistat(), shipXyInfoDto.getLat(), shipXyInfoDto.getGLat(),
                                shipXyInfoDto.getLon(), shipXyInfoDto.getGLon(), shipXyInfoDto.getSog(), shipXyInfoDto.getCityName(), shipXyInfoDto.getLastTime());
                        berthInfoDtoList.add(berthInfoDto);
                        break;
                    }
                }
            }
        }

        //批量插入，1000条一次
        int size = berthInfoDtoList.size();
        int x = size/1000;
        int y = size%1000;
        for (int i = 0; i < x; i++) {
            int start = i*1000;
            int end = (i + 1) * 1000;
            List<BerthInfoDto> subList = berthInfoDtoList.subList(start,end);
            iShipDao.insertBerthInfo(subList);
        }

        if (y > 0) {
            List<BerthInfoDto> subList = berthInfoDtoList.subList(x*1000,size);
            iShipDao.insertBerthInfo(subList);
        }
    }

    private void getCityName4GD(StringBuffer sb, List<ShipXyInfoDto> shipXyInfoDtoList, List<ShipXyInfoDto> shipXyInfoDtoList1) {
        String zb;
        try {
            zb = URLEncoder.encode(sb.substring(0, sb.length() -1), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return;
        }
        String URL = "https://restapi.amap.com/v3/geocode/regeo?location=ZB&output=JSON&key=3efa2c4d5ab9b7995b8306774ef73471&batch=PL";
        String reqUrl = URL.replaceAll("ZB", zb).replaceAll("PL","true");
        JSONObject object = HttpUtil.get(reqUrl);
//        String status = object.getString("status");
        String status = JsonUtil.getJSONObjectString2(object, "status");
        if ("1".equals(status)) {
            JSONArray jsonArray = object.getJSONArray("regeocodes");
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject1 = (JSONObject) jsonArray.get(i);
                JSONObject addressComponent = jsonObject1.getJSONObject("addressComponent");
                String city = addressComponent.getString("city");
                if ("[]".equals(city)) {
                    city = addressComponent.getString("province");
                }
//                String district = addressComponent.getString("district");

                ShipXyInfoDto shipXyInfoDto1 = shipXyInfoDtoList1.get(i);
                for (ShipXyInfoDto shipXyInfoDto : shipXyInfoDtoList) {
                    if (shipXyInfoDto1.getMmsi().equals(shipXyInfoDto.getMmsi())) {
//                        shipXyInfoDto.setCityName(city+district);
                        shipXyInfoDto.setCityName(city);
                        break;
                    }
                }
            }
        }
        else {
            logger.info("getCityName4GD error sb:{}, object:{}", sb, object);
        }
    }

    private Boolean checkZBIsRight(String str) {
        try
        {
            if (Double.parseDouble(str) != 0) {
                return true;
            }
        }catch (Exception e) {
            return false;
        }
        return false;
    }

    private void getLocations(StringBuffer sb, List<ShipXyInfoDto> shipXyInfoDtoList, List<ShipXyInfoDto> shipXyInfoDtoList1) {
        String zb;
        try {
            zb = URLEncoder.encode(sb.substring(0, sb.length() -1), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return;
        }
        String url = "https://restapi.amap.com/v3/assistant/coordinate/convert?locations=ZB&coordsys=gps&key=3efa2c4d5ab9b7995b8306774ef73471";
        String reqUrl = url.replaceAll("ZB", zb);
        JSONObject object = HttpUtil.get(reqUrl);
        if (null != object) {
            String status = object.getString("status");
            if ("1".equals(status)) {
                String locations = object.getString("locations");
                String[] locationsArr = locations.split(";");
                for (int i = 0; i < locationsArr.length; i++) {
                    String[] locationArr = locationsArr[i].split(",");
                    ShipXyInfoDto shipXyInfoDto = shipXyInfoDtoList1.get(i);
                    for (ShipXyInfoDto shipXyInfoDto2 : shipXyInfoDtoList) {
                        if (shipXyInfoDto.getMmsi().equals(shipXyInfoDto2.getMmsi())) {
                            shipXyInfoDto2.setGLat(locationArr[1]);
                            shipXyInfoDto2.setGLon(locationArr[0]);
                            break;
                        }
                    }
                }
            }
        }
    }

    private List<ShipXyInfoDto> selectAllShipMMSI() {
        logger.info("ShipXyServices getShipIdMMSI");
        return iShipDao.selectAllShipMMSI();
    }

    @Autowired
    private ITransportPlanDao iTransportPlanDao;

    @Scheduled(fixedDelay = 3600 * 24 * 1000)
    //一天执行一次
    public void updateTuiSongShip() {
        logger.info("ShipXyServices updateTuiSongShip start date:{}", DateUtil.getStandardNowTime());
        //上传最新的mmsi到船讯网推送
        List<String> mmsiList = iTransportPlanDao.queryAllMMSI();

        StringBuilder sb = new StringBuilder();
        for (String mmsi : mmsiList) {
            sb.append(mmsi).append(",");
        }
        if (sb.length() > 0) {
            JSONObject object = new JSONObject();
            object.put("shipIds", sb.substring(0, sb.length() - 1));
            object = ShipXyAPIUtil.updateShips(object);
            if (!"0".equals(JsonUtil.getJSONObjectString(object, "status"))) {
                logger.error("------------------------------------------------");
                logger.error("ShipXyServices updateTuiSongShip error:{},sb:{}", object,sb);
                logger.error("------------------------------------------------");
            }
        }
        //删除一个月以前的推送
//        iTransportPlanDao.deleteShipXyInfo(DateUtil.date2String(DateUtil.offsetDay(new Date(), -31), "YYYY-MM-DD HH:mm"));
    }
}
